﻿using Handday.Erp.Core;
using Microsoft.Extensions.Logging;
using Quartz;
using RedLockNet;
using System;
using System.Diagnostics;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;

namespace Handday.Erp.JobTask
{
    /// <summary>
    /// quartz common job
    /// </summary>
    public class CommonJob : IJob
    {
        private readonly ILogger<CommonJob> _logger;
        private readonly IHttpClientFactory _httpClientFactory;
        private readonly BaseApiUrl _baseApiUrl;
        private readonly IDistributedLockFactory _distributedLockFactory;

        /// <summary>
        /// ctor
        /// </summary>
        public CommonJob(
            ILogger<CommonJob> logger,
            IHttpClientFactory httpClientFactory,
            IDistributedLockFactory distributedLockFactory,
            BaseApiUrl baseApiUrl)
        {
            _logger = logger;
            _httpClientFactory = httpClientFactory;
            _distributedLockFactory = distributedLockFactory;
            _baseApiUrl = baseApiUrl;
        }

        /// <summary>
        /// 执行接口请求
        /// </summary>
        public async Task Execute(IJobExecutionContext context)
        {
            var url = string.Empty;
            try
            {
                var watch = new Stopwatch();
                watch.Start();
                url = _baseApiUrl.HanddayBaseUrl + context.JobDetail.JobDataMap.Get("ApiUrl").ToString().TrimStart('/');
                await using (var redisLock = await _distributedLockFactory.CreateLockAsync($"erp_transfer_{url}", TimeSpan.FromSeconds(20)))
                {
                    if (!redisLock.IsAcquired)
                    {
                        _logger.LogInformation($"erp.transfer.job.concurrency.error ：{url}");
                        return;
                    }

                    _logger.LogInformation($"erp.transfer.job.request ：{url}");

                    using var client = _httpClientFactory.CreateClient();
                    var response = await client.PostAsJsonAsync(url, new object());
                    var result = await response.Content.ReadAsStringAsync();

                    _logger.LogInformation($"erp.transfer.job.response ：{url}；status_code：{response.StatusCode}； result：{JsonSerializer.Serialize(result)}");
                    watch.Stop();

                    //防止任务执行时间太短，多终端并发。
                    var delayMilliSec = 5000 - watch.ElapsedMilliseconds;
                    if (delayMilliSec > 0)
                    {
                        await Task.Delay((int)delayMilliSec);
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"erp.transfer.job.error ：{url}；error：{ex.Message}_{ex.InnerException?.Message}；");
                throw;
            }
        }
    }
}
